//
//    Render to VB
//


-- VS

layout(location=0) in vec2 inPosition;

out block {
  ivec3 coords_case_numTri;
} Out;

uniform sampler3D uDensityVolume;
uniform isamplerBuffer uCaseToNumTri;
//uniform float uInvChunkDimMinusOne;
uniform vec2 uTexelSize;




void main()
{
  ivec3 coords = ivec3( inPosition.xy, gl_InstanceID);
  int packed_coords = (coords.x << 0) | (coords.y << 6) | (coords.z << 12);  



  const vec3 uvw = coords * (1.0f/32.0f);//uInvChunkDimMinusOne;
  const vec2 texelSize = uTexelSize;//vec2( uInvChunkDim, 0.0f);//
  
  vec4 sideA;
  vec4 sideB;
  
          //textureOffset( uDensityVolume, uvw, texelSize.yyy); ?
  sideA.x = texture( uDensityVolume, uvw + texelSize.yyy).r; 
  sideA.y = texture( uDensityVolume, uvw + texelSize.yxy).r;
  sideA.z = texture( uDensityVolume, uvw + texelSize.xxy).r;
  sideA.w = texture( uDensityVolume, uvw + texelSize.xyy).r;
  
  sideB.x = texture( uDensityVolume, uvw + texelSize.yyx).r;
  sideB.y = texture( uDensityVolume, uvw + texelSize.yxx).r;
  sideB.z = texture( uDensityVolume, uvw + texelSize.xxx).r;
  sideB.w = texture( uDensityVolume, uvw + texelSize.xyx).r;
  
  // 0 if value < 0.0f, 1 otherwise
# define SATURATE(v)  ivec4(clamp( 0x8000*(v), 0, 1))    // OR step(0, v)
  ivec4 iA = SATURATE(sideA);
  ivec4 iB = SATURATE(sideB);
# undef SATURATE
  
  int cube_case = (iA.x << 0) | (iA.y << 1) | (iA.z << 2) | (iA.w << 3) |
                  (iB.x << 4) | (iB.y << 5) | (iB.z << 6) | (iB.w << 7);
  
  
  int numTri = texelFetch( uCaseToNumTri, cube_case).r;
  
  
  Out.coords_case_numTri.x = packed_coords;
  Out.coords_case_numTri.y = cube_case;
  Out.coords_case_numTri.z = numTri;
}

--

//------------------------------------------------------------------------------

-- GS

//TODO unroll the loop

layout(points) in;
layout(points, max_vertices = 5) out;

in block {
  ivec3 coords_case_numTri;
} In[];

out int x6y6z6_e4e4e4;

// size: 1280 * short [3 x 4bits]
uniform isamplerBuffer uEdgeConnectList;


void main()
{  
# define PackedCoords  In[0].coords_case_numTri.x
# define CubeCase      In[0].coords_case_numTri.y
# define NumTri        In[0].coords_case_numTri.z
  
  
  for (int i=0; i<NumTri; ++i)
  {    
    int offset = int(5*CubeCase + i);
    int packed_edges = texelFetch( uEdgeConnectList, offset).r;
    
    x6y6z6_e4e4e4 = PackedCoords | (packed_edges << 18);
    EmitVertex();
  }  
  EndPrimitive();
}

